home *** CD-ROM | disk | FTP | other *** search
/ Your Choice 3 / Your Choice Software Collection 3.iso / prgmming / atbus / atbus.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1994-01-25  |  10.4 KB  |  302 lines

  1. {---------------------------------------------------------------------------
  2.   PROGRAM :       ATBUS                           INITIAL : 19910404 v 1.00
  3.   PROJECT :       ATBUS                           UPDATE :  19940126 v 1.02
  4.   AUTHOR :        Martin Gerdes
  5.                   English version by Jeroen W. Pluimers
  6.                   internet: jeroenp@dragons.nest.nl
  7.                   compuserve: 100013,1443
  8.  
  9.   DESCRIPTION :   Describe AT-BUS hard-disk parameters
  10.  
  11.   HISTORY :       19910404 - 1.00 - initial German Version
  12.                   19920205 - 1.01 - initial English Version
  13.                   19940126 - 1.02 - added string endian reversion
  14.                                     (some HD-manufacturers have strings
  15.                                      with little-endian, others encode
  16.                                      with big-endian)
  17.  
  18.   COMPUTER :      ERC 386/25; BSE 486/50
  19.   COMPILER :      Turbo Pascal 6.0; Borland Pascal 7.01
  20.  
  21.   COPYRIGHT :     Original version (c) Martin Gerdes und c't 1991
  22.                   English version (c) 1991 Pluimers Software Ontwikkeling.
  23.  ---------------------------------------------------------------------------}
  24.  
  25. program AtBus;
  26.  
  27. {$A+,B-,D+,E+,F-,I+,L+,N-,O-,R-,S-,V-,X+}
  28. {$M 2048,0,0}
  29.  
  30. var
  31.   ExitSave    :Pointer;
  32.  
  33. const
  34.   ide_Data        = $1F0;
  35.   ide_Error       = $1F1;
  36.   ide_SectorCount = $1F2;
  37.   ide_Sector      = $1F3;
  38.   ide_CylinderLo  = $1F4;
  39.   ide_CylinderHi  = $1F5;
  40.   ide_DriveAndHead= $1F6;
  41.   ide_Status      = $1F7;
  42.   ide_Command     = $1F7;
  43.  
  44. const
  45.   icf_Reserved                        = $0001;
  46.   icf_HardSectored                    = $0002;
  47.   icf_SoftSectored                    = $0004;
  48.   icf_NoCodingMFM                     = $0008;
  49.   icf_SeekTime15mu                    = $0010;
  50.   icf_CanTurnMotorOff                 = $0020;
  51.   icf_IsFixedDisk                     = $0040;
  52.   icf_IsRemovableDisk                 = $0080;
  53.   icf_LessThan5Mbs                    = $0100;
  54.   icf_5MbsInside10Mbs                 = $0200;
  55.   icf_MoreThan10Mbs                   = $0400;
  56.   icf_RotationToleranceHalfPercent    = $0800;
  57.   icf_HasDataStrobeOffsetOption       = $1000;
  58.   icf_HasTrackOffsetOption            = $2000;
  59.   icf_RequiresFormatSpeedToleranceGap = $4000;
  60.   icf_IsNonMagneticDrive              = $8000;
  61.  
  62.   ict_NotSpecified                         = 0;
  63.   ict_SinglePortedSingleSectorBuf          = 1;
  64.   ict_DualPortedMultipleSectorBuf          = 2;
  65.   ict_DualPortedMultipleSectorBufReadAhead = 3;
  66.  
  67. type
  68.   Char8  = array [0..7 ] of Char;
  69.   Char20 = array [0..19] of Char;
  70.   Char40 = array [0..39] of Char;
  71.   tDescIDE = Record
  72.     ConfigFlags:        Word;   { see icf_xxx constants }
  73.     FixedCylinders:     Word;
  74.     RemovableCylinders: Word;
  75.     Heads:              Word;
  76.     BytesPerTrack:      Word;
  77.     BytesPerSector:     Word;
  78.     SectorsPerTrack:    Word;
  79.     d1,d2,d3:           Word;
  80.     SerialNumber:       Char20;
  81.     ControllerType:     Word;   { see ict_xxx constants }
  82.     SectorsInBuffer:    Word;   { each sector is 512 bytes }
  83.     ECCBytes:           Word;
  84.     ControllerRevision: Char8;
  85.     ControllerModel:    Char40;
  86.     SectorsPerInterupt: Word;
  87.     DoubleWordFlag:     Word;
  88.     IsWriteProtected:   Word;
  89.     reserved:           array [50..255] of Word;
  90.   end;
  91.  
  92. function Byte2Hex(h:byte):string;
  93. const
  94.   hexarray: array [0..15] of char = '0123456789abcdef';
  95. begin
  96.   Byte2Hex:=hexarray[h shr 4]+hexarray[h and $f];
  97. end;
  98.  
  99. function Word2Hex(h:word):string;
  100. begin
  101.   Word2Hex:=Byte2Hex(hi(h)) + Byte2Hex(lo(h));
  102. end;
  103.  
  104. function GetConfigFlag (Flag: Word): String;
  105. var
  106.   s : String;
  107. begin
  108.   case Flag of
  109.     icf_Reserved                       : s := 'has reserved flag';
  110.     icf_HardSectored                   : s := 'is hard-sectored';
  111.     icf_SoftSectored                   : s := 'is soft-sectored';
  112.     icf_NoCodingMFM                    : s := 'has no MFM encoding';
  113.     icf_SeekTime15mu                   : s := 'has seek time > 15 µs';
  114.     icf_CanTurnMotorOff                : s := 'can turn off drive motor';
  115.     icf_IsFixedDisk                    : s := 'has a permanent hard-disk';
  116.     icf_IsRemovableDisk                : s := 'has a removable disk';
  117.     icf_LessThan5Mbs                   : s := 'has a transferrate <= 5 Mb/s';
  118.     icf_5MbsInside10Mbs                : s := 'has a transferrate > 5 Mb/s and <= 10 Mb/s';
  119.     icf_MoreThan10Mbs                  : s := 'has a transferrate > 10 Mb/s';
  120.     icf_RotationToleranceHalfPercent   : s := 'has a rotation speed tolerance > 0.5%';
  121.     icf_HasDataStrobeOffsetOption      : s := 'has a data strobe offset option available';
  122.     icf_HasTrackOffsetOption           : s := 'has a track offset option available';
  123.     icf_RequiresFormatSpeedToleranceGap: s := 'has a format speed tolerance gap required';
  124.     icf_IsNonMagneticDrive             : s := 'is a non-magnetic drive'
  125.     else                                 s := 'an invalid flag : '+Word2Hex(Flag);
  126.   end;
  127.   GetConfigFlag := s;
  128. end;
  129.  
  130. function GetControllerType (Controller: Word): String;
  131. var
  132.   s : String;
  133. begin
  134.   Case Controller of
  135.     ict_NotSpecified                         : s := 'not specified';
  136.     ict_SinglePortedSingleSectorBuf          : s := 'single ported single sector buffer';
  137.     ict_DualPortedMultipleSectorBuf          : s := 'dual ported multiple sector buffer';
  138.     ict_DualPortedMultipleSectorBufReadAhead : s := 'dual ported multiple sector buffer with look-ahead read capabilities';
  139.   end;
  140.   GetControllerType := s;
  141. end;
  142.  
  143. Function StripString (s: String): String;
  144. Begin
  145.   while (s[length(s)]=#0) and (length(s)<>0) do
  146.     delete(s,length(s),1);
  147.   StripString := '>'+s+'<';
  148. End;
  149.  
  150. function StrChangeEndian(s: String): String;
  151.   { change from big-endian words into little-endian words }
  152. var
  153.   i: byte;
  154.   c: char;
  155. begin
  156.   for i := 1 to length(s) do if not odd(i) then begin
  157.     c := s[i];
  158.     s[i] := s[i-1];
  159.     s[i-1] := c;
  160.   end;
  161.   StrChangeEndian := s;
  162. end;
  163.  
  164. {$F+} procedure MyExit; {$F-}
  165. { reset disk parameters so other disk operations won't be desturbed in case
  166.   of program abort }
  167. begin
  168.   Port[ide_Command]:=$10;      { send command: reset current drive }
  169.   Port[ide_DriveAndHead]:=$a0; { select drive 0, head 0 }
  170.   Port[ide_Command]:=$10;      { send command: reset current drive }
  171.   ExitProc := ExitSave;        { restore previous exitproc }
  172. end;
  173.  
  174. function ReadIDE (Var DescIDE: tDescIDE): Boolean; assembler;
  175. asm
  176.   cld                     { string direction forward }
  177.   les   di, [DescIDE]     { load description table into destination }
  178.   mov   dx, ide_Command
  179.   mov   al, 0ECh
  180.   out   dx, al
  181.   jmp   @@0
  182. @@0:
  183.   mov   cx, 0
  184. @@Loop1:
  185.   in    al, dx            { wait until the controller says its ready }
  186.   and   al, 08h
  187.   jnz   @@GotDesc
  188.   loop  @@Loop1
  189.   mov   ax, False         { indicate failure }
  190.   mov   cx, 100h          { and fill table with 0 }
  191.   rep   stosw
  192.   jmp   @@Exit
  193. @@GotDesc:
  194.   mov   cx, 100h          { get 0100h words }
  195.   mov   dx, ide_Data     
  196. @@Loop2:
  197.   in    ax, dx
  198.   stosw
  199.   loop  @@Loop2
  200.   mov   al, true
  201. @@Exit:
  202. end;
  203.  
  204. procedure ResetCurrentDrive;
  205. begin
  206.   Port [ide_Command] := $10;
  207. end;
  208.  
  209. function SetDrive (Drive: Char): Boolean;
  210. begin
  211.   SetDrive := true;
  212.   case Drive of
  213.     'C': port[ide_DriveAndHead] := $a0;
  214.     'D': port[ide_DriveAndHead] := $b0;
  215.   else
  216.     SetDrive := false; { only two IDE drives allowed }
  217.   end;
  218. end;
  219.  
  220. procedure WriteReport(Drive:Char);
  221.   { ask status of drive and report it }
  222. var
  223.   i           :Word;
  224.   ch          :Char;
  225.   boo         :Boolean;
  226.   TotalSectors:LongInt;
  227.  
  228.   DescIDE : tDescIDE;
  229. begin
  230.   Drive := Upcase(Drive);
  231.   Writeln;
  232.   Writeln('Disk-drive ',Drive,':');
  233.   Writeln('═════════════');
  234.  
  235.   If not SetDrive (Drive) then exit;
  236.  
  237.   boo := ReadIDE (DescIDE) and ((Port[ide_Status] and 1) = 0);
  238.  
  239.   { before doing output, reset to drive D: so output
  240.     redirection will function properly }
  241.  
  242.   SetDrive ('C');
  243.   ResetCurrentDrive;
  244.  
  245.   if boo Then
  246.     with DescIDE do begin
  247.       Writeln('Configuration              : $', Word2Hex(ConfigFlags));
  248.       for i := 0 TO 15 do
  249.         if ConfigFlags and (1 shl i) <> 0 then
  250.             Writeln ('  '+GetConfigFlag(1 shl i));
  251.       Writeln;
  252.  
  253.       Writeln('Number of cylinders on');
  254.       Writeln(' non-removable medium      : ',FixedCylinders);
  255.       Writeln(' removable medium          : ',RemovableCylinders);
  256.       Writeln('Number of heads            : ',Heads);
  257.       Writeln('Bytes per track            : ',BytesPerTrack);
  258.       Writeln('Bytes per sector           : ',BytesPerSector);
  259.       Writeln('Sectors per track          : ',SectorsPerTrack);
  260.       Writeln('d1                         : ',Word2Hex(d1));
  261.       Writeln('d2                         : ',Word2Hex(d2));
  262.       Writeln('d3                         : ',Word2Hex(d3));
  263.       Writeln('Serial number              : ',StripString(SerialNumber));
  264.       Writeln('                             ',StripString(StrChangeEndian(SerialNumber)));
  265.       Writeln('Controller type            : ',GetControllerType(ControllerType));
  266.       Writeln('Buffersize in sectors      : ',SectorsInBuffer);
  267.       Writeln('Number of ECC-bytes        : ',ECCBytes);
  268.       Writeln('Controller Revision        : ',StripString(ControllerRevision));
  269.       Writeln('                             ',StripString(StrChangeEndian(ControllerRevision)));
  270.       Writeln('Controller model           : ',StripString(ControllerModel));
  271.       Writeln('                             ',StripString(StrChangeEndian(ControllerModel)));
  272.       Writeln('Sectors per interrupt      : ',SectorsPerInterupt);
  273.       Writeln('Double word flag           : ',DoubleWordFlag);
  274.       Writeln('Write protect flag         : ',IsWriteProtected);
  275.       Writeln;
  276.       TotalSectors:=LongInt(FixedCylinders+RemovableCylinders) *
  277.                     LongInt(Heads) * LongInt(SectorsPerTrack);
  278.       Writeln('Total sectors              : ',TotalSectors);
  279.       Writeln('Total capacity (Megabytes) : ',TotalSectors DIV 2048);
  280.       { 512 byte per sector -> 2048 sectors per megabyte }
  281.  
  282.       For i := 50 to 255 do if reserved[i] <> 0 then
  283.       Writeln('Reserved',i:7,'            : ',Reserved[i]);
  284.     end { with }
  285.   else
  286.     Writeln('is not available.');
  287. END;
  288.   {----------------------------------------------------}
  289.  
  290. BEGIN
  291.   ExitSave:=ExitProc;
  292.   ExitProc:= @MyExit;
  293.  
  294.   Writeln('*** ATBUS ***  04.04.91 -mat 19940126 -jwp');
  295.   Writeln('A program that shows disk-drive parameters from IDE disks');
  296.  
  297.   WriteReport('c');
  298.   WriteReport('d');
  299.   Writeln;
  300. END.
  301.  
  302.